package com.multitrack.map;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.location.Address;
import android.location.Criteria;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;

import com.facebook.android.Facebook;
import com.facebook.android.SessionStore;
import com.facebook.android.Utility;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.OverlayItem;
import com.multitrack.main.R;
import com.multitrack.map.datatype.CustomMapView;
import com.multitrack.map.datatype.CustomMapView.OnLongPressListener;
import com.multitrack.map.datatype.MapBasic;
import com.multitrack.map.datatype.Marker;
import com.multitrack.map.datatype.Polyline;
import com.multitrack.map.util.Convert;

public class BasicMapActivity extends MapActivity implements MapBasic {

	private final String TAG = "BasicMapActivity";

	protected enum CTRL_STATE {
		PLAY, PAUSE, STOP, ;
	}

	// Map Set Values
	protected final int ZOOM_LEVEL = 13;

	protected String mProvider;
	protected LocationManager mLocMan;
	protected int locProviderState;

	protected CustomMapView mCustomMap;
	protected MapController mapControl;
	protected AutoLocationOverlay mAutoLoc;

	// GPS Set
	protected long minTime;
	protected float minDistance;

	// Draw Line
	protected Polyline lines;

	// Draw Marker
	protected Marker beginMarker;
	protected Marker flagMarker;

	protected OverlayItem startItem;
	protected OverlayItem flagItem;

	protected GeoPoint targetPoint;
	protected GeoPoint searchPoint;

	// Controller
	protected CTRL_STATE ctrlState;
	protected ImageView imgPlay;
	protected ImageView imgPause;
	protected ImageView imgStop;

	// Search Target
	private static final int MAX_RESULT = 5;
	private Geocoder mCoder;
	private ListView destinationList;
	private List<Address> addressList;
	private ArrayAdapter<String> dAdapter;
	private ArrayList<String> addressNames;
	private String addressName;
	private EditText destinationName;
	private InputMethodManager imm;
	protected LinearLayout dLayout;

	@Override
	public void onResume() {
		super.onResume();
		mAutoLoc.enableMyLocation();
		mAutoLoc.enableCompass();
		mLocMan.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTime,
				minDistance, this);
	}

	@Override
	public void onPause() {
		super.onPause();
		mAutoLoc.disableMyLocation();
		mAutoLoc.disableCompass();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		mLocMan.removeUpdates(this);
	}

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.custom_map_activity);
		setLocationUpdates(5000, 3);

		// 위치 관리자 얻기
		mLocMan = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

		// 최적 제공자 조사
		Criteria crit = new Criteria();
		crit.setAccuracy(Criteria.NO_REQUIREMENT);
		crit.setPowerRequirement(Criteria.NO_REQUIREMENT);
		crit.setAltitudeRequired(false);
		crit.setCostAllowed(false);

		// 제공자 설정 - 수정 필요
		Location beforeLoc;
		mProvider = mLocMan.getBestProvider(crit, true);
		try {
			beforeLoc = mLocMan.getLastKnownLocation(mProvider);
		} catch (Exception e) {
			beforeLoc = null;
		}

		mCustomMap = (CustomMapView) findViewById(R.id.customMapView);

		// 맵 컨트롤
		mapControl = mCustomMap.getController();
		mapControl.setZoom(ZOOM_LEVEL);
		mCustomMap.setBuiltInZoomControls(true);

		// 시작 위치 설정
		GeoPoint pt;
		if (beforeLoc == null) {
			pt = new GeoPoint(37881311, 127729968);
		} else {
			pt = new GeoPoint((int) (beforeLoc.getLatitude() * 1E6),
					(int) (beforeLoc.getLongitude() * 1E6));
		}
		mapControl.setCenter(pt);

		mAutoLoc = new AutoLocationOverlay(getApplicationContext(), mCustomMap);
		mCustomMap.getOverlays().add(mAutoLoc);
		mAutoLoc.runOnFirstFix(new Runnable() {

			public void run() {
				mCustomMap.getController().animateTo(mAutoLoc.getMyLocation());
			}
		});

		// 커스텀 맵뷰 리스너
		OnLongPressListener listener = new CustomMapView.OnLongPressListener() {
			public void onLongPress(final MapView mapView,
					final GeoPoint longPressLocation) {
				runOnUiThread(new Runnable() {
					public void run() {
						searchPoint = mCustomMap.getLongPressLocation();
						onShowDialog();
					}
				});
			}
		};
		mCustomMap.setOnLongPressListener(listener);

		// 마커 그림 등록
		beginMarker = new Marker(mCustomMap, getApplicationContext(),
				R.drawable.start);
		flagMarker = new Marker(mCustomMap, getApplicationContext(),
				R.drawable.pin_color);

		// 컨트롤러 이미지 설정
		imgPlay = (ImageView) findViewById(R.id.imgPlay);
		imgPause = (ImageView) findViewById(R.id.imgPause);
		imgStop = (ImageView) findViewById(R.id.imgStop);

		setCtrlState(CTRL_STATE.STOP);
		updateControllerImg(ctrlState);

		lines = new Polyline();

		// 주소 검색
		dLayout = (LinearLayout) findViewById(R.id.destination_layout);
		destinationList = (ListView) findViewById(R.id.destination_list);
		mCoder = new Geocoder(this);
		addressNames = new ArrayList<String>();
		dAdapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1, addressNames);
		destinationList.setAdapter(dAdapter);
		destinationList.setOnItemClickListener(dListener);
		destinationName = (EditText) findViewById(R.id.destination_edit);
		imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
	}

	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		menu.clear();
		Utility.mFacebook = new Facebook(getResources().getString(
				R.string.facebook_app_id));
		SessionStore.restore(Utility.mFacebook, this);
		if (Utility.mFacebook.isSessionValid())
			getMenuInflater().inflate(R.menu.facebook_logined_menu, menu);
		else
			getMenuInflater().inflate(R.menu.facebook_logouted_menu, menu);
		return true;
	}

	public void setLocationUpdates(long minTime, float minDistance) {
		this.minTime = minTime;
		this.minDistance = minDistance;
	}

	public void onShowDialog() {
		// TODO:
	}

	/**
	 * 
	 */
	protected CTRL_STATE getCtrlState() {
		return this.ctrlState;
	}

	protected void setCtrlState(CTRL_STATE state) {
		this.ctrlState = state;
	}

	protected void updateControllerImg(CTRL_STATE state) {
		switch (state) {
		case PLAY:
			imgPlay.setVisibility(View.INVISIBLE);
			imgPause.setVisibility(View.VISIBLE);
			imgStop.setVisibility(View.VISIBLE);
			break;

		case PAUSE:
			imgPlay.setVisibility(View.VISIBLE);
			imgPause.setVisibility(View.INVISIBLE);
			imgStop.setVisibility(View.VISIBLE);
			break;

		case STOP:
			imgPlay.setVisibility(View.VISIBLE);
			imgPause.setVisibility(View.INVISIBLE);
			imgStop.setVisibility(View.INVISIBLE);
			break;
		}
	}

	// 컨트롤러 이미지 클릭 메소드
	public void mOnClick(View v) {
		switch (v.getId()) {

		case R.id.imgPlay:
			// 시작 시 현제 GPS 상황 체크 안내 메시지
			setCtrlState(CTRL_STATE.PLAY);
			break;

		case R.id.imgPause:
			setCtrlState(CTRL_STATE.PAUSE);
			break;

		case R.id.imgStop:
			setCtrlState(CTRL_STATE.STOP);
			break;

		default:
			return;
		}
		updateControllerImg(ctrlState);
	}

	public void mSearchOnClick(View v) {

		addressName = destinationName.getText().toString();
		String tempAddress;

		switch (v.getId()) {
		case R.id.search_btn:

			if (addressName == null) {
				Toast.makeText(this, R.string.input_address, Toast.LENGTH_SHORT)
						.show();
				return;
			}
			try {
				addressList = mCoder.getFromLocationName(addressName,
						MAX_RESULT);
				addressNames.clear();

				for (int i = 0; i < addressList.size(); i++) {
					tempAddress = addressList.get(i).getAddressLine(i);
					if (tempAddress == null) {
						addressList.remove(i--);
						continue;
					}
					addressNames.add(tempAddress);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			dAdapter.notifyDataSetChanged();
			if (addressNames.size() == 0) {
				Toast.makeText(this, R.string.no_result, Toast.LENGTH_SHORT)
						.show();
				return;
			}
			break;
		}
	}

	AdapterView.OnItemClickListener dListener = new AdapterView.OnItemClickListener() {

		public void onItemClick(AdapterView<?> parent, View view, int pos,
				long id) {
			searchPoint = Convert.toGeoPoint(
					addressList.get(pos).getLatitude(), addressList.get(pos)
							.getLongitude());
			mapControl.animateTo(searchPoint);
			dLayout.setVisibility(View.GONE);
			imm.hideSoftInputFromWindow(destinationName.getWindowToken(), 0);

			onShowDialog();
		}
	};

	class AutoLocationOverlay extends MyLocationOverlay {
		public AutoLocationOverlay(Context context, MapView mapView) {
			super(context, mapView);
		}

		protected boolean dispatchTap() {
			// 현재 위치에 대한 처리가 완료되지 않게 하기 위한 false 리턴
			return false;
		}
	}

	// location을 하나씩 받아 그리는 함수
	public void drawLine(Location location) {
		GeoPoint currPoint = Convert.toGeoPoint(location);
		mCustomMap.getOverlays().remove(lines);
		if(lines.size() < 2) {
			beginMarker.draw(currPoint, null, null);
		}
		lines.add(currPoint);
		mCustomMap.getOverlays().add(lines);
		mCustomMap.invalidate();
	}

	public void onLocationChanged(Location location) {
		// TODO Auto-generated method stub

	}

	public void onProviderDisabled(String provider) {
		// 서비스 사용 불가
	}

	public void onProviderEnabled(String provider) {
		// 서비스 사용 가능
	}

	public void onStatusChanged(String provider, int status, Bundle extras) {
		switch (status) {
		case LocationProvider.OUT_OF_SERVICE:
			// 범위 벗어남
			break;
		case LocationProvider.TEMPORARILY_UNAVAILABLE:
			// 일시적 불능
			break;
		case LocationProvider.AVAILABLE:
			// 사용 가능
			break;
		}
		locProviderState = status;
	}

	@Override
	public boolean onKeyUp(int KeyCode, KeyEvent event) {

		if (event.getAction() == KeyEvent.ACTION_UP) {
			switch (KeyCode) {

			case KeyEvent.KEYCODE_BACK:
				onKeyUpBack();
				return true;
			}
		}
		return false;
	}

	protected void onKeyUpBack() {
		// TODO Auto-generated method stub
	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

}
